﻿using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Kevin.Code.Generator.DbAccessor.Models;
using Kevin.Code.Generator.Infrastructure.Models;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using Yitter.IdGenerator;

namespace Kevin.Code.Generator.Api
{
    /// <summary>
    /// 代码生成
    /// </summary>
    public partial class CodeGeneratorService : IDynamicApiController, ITransient
    {
        /// <summary>
        /// 获取所有的链接
        /// </summary>
        /// <returns></returns>
        [HttpGet, QueryParameters]
        public async Task<List<SimpleDto<long>>> ListDbLinks()
        {
            var data = await _repository.Queryable<DB_Connection>().OrderBy(dc => dc.Create_Time, OrderByType.Desc).ToListAsync();
            return data.Adapt<List<SimpleDto<long>>>();
        }

        /// <summary>
        /// 添加链接
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet, QueryParameters]
        public async Task AddDbLink(DB_ConnectionInput input)
        {
            var dbConnection = input.Adapt<DB_Connection>();
            dbConnection.Id = YitIdHelper.NextId();
            dbConnection.Create_Time = DateTime.Now;
            await _repository.Insertable<DB_Connection>(dbConnection).ExecuteCommandAsync();
        }

        /// <summary>
        /// 修改链接
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet, QueryParameters]
        public async Task UpdateDbLink(DB_ConnectionInput input)
        {
            var dbConnection = input.Adapt<DB_Connection>();
            await _repository.Updateable<DB_Connection>(dbConnection).ExecuteCommandAsync();
        }

        /// <summary>
        /// 删除数据库链接
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet, QueryParameters]
        public async Task DeleteDbLink(IdInput<long> input)
        {
            await _repository.Deleteable<DB_Connection>().Where(dc => dc.Id == input.Id).ExecuteCommandAsync();
        }

        /// <summary>
        /// 获取表列表
        /// </summary>
        /// <param name="dbLinkId"></param>
        /// <returns></returns>
        [HttpGet, QueryParameters]
        public async Task<List<string>> ListTables(long dbLinkId)
        {
            var (tables, sugarClient) = await GetAllTables(dbLinkId);
            return tables;
        }

        /// <summary>
        /// 获取字段列表
        /// </summary>
        /// <param name="dbLinkId"></param>
        /// <param name="tableName"></param>
        /// <returns></returns>
        [HttpGet, QueryParameters]
        public async Task<List<string>> ListColumns(long dbLinkId, string tableName)
        {
            var (tables, sugarClient) = await GetAllTables(dbLinkId);
            if (tables == null || tables.Count == 0 || !tables.Contains(tableName))
                throw Oops.Bah("表名不存在");
            var columns = sugarClient.DbMaintenance.GetColumnInfosByTableName(tableName, false);
            return columns.Select(c => c.DbColumnName).ToList();
        }

        /// <summary>
        /// 生成代码
        /// </summary>
        /// <param name="codeRuleInput">生成代码规则</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> GenerateCode(CodeRuleInput codeRuleInput)
        {
            var input = new GeneratorTplModel
            {
                ProjectName = "双创科服测试项目",
                ProjectNameSpace = "Sckf.Test.",
                ModelClassName = "Admin",
                CreateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
            };
            var zipBytes = await GeneratorCodeHelper.CreateZip(zip =>
            {
                GeneratorCodeHelper.GenerateInterfaceCode(zip, input);
            });

            return new FileStreamResult(new MemoryStream(zipBytes), "application/octet-stream") { FileDownloadName = $"Code.zip" };
        }
    }

    public partial class CodeGeneratorService
    {
        private readonly SqlSugarClient _repository;

        /// <summary>
        /// CodeGeneratorService
        /// </summary>
        /// <param name="repository"></param>
        public CodeGeneratorService(ISqlSugarRepository repository)
        {
            _repository = repository.Context;
        }

        private SqlSugarClient GenerateSqlSugarClient(DB_Connection dbLink)
        {
            return new SqlSugarClient(new ConnectionConfig()
            {
                ConnectionString = dbLink.Connection_String,
                DbType = (DbType)dbLink.Type,
                IsAutoCloseConnection = true
            });
        }

        /// <summary>
        /// 获取所有的表名
        /// </summary>
        /// <param name="dbLinkId">链接id</param>
        /// <returns></returns>
        private async Task<(List<string> tables, SqlSugarClient sugarClient)> GetAllTables(long dbLinkId)
        {
            var dbConnection = await _repository.Queryable<DB_Connection>().SingleAsync(dc => dc.Id == dbLinkId);
            if (dbConnection == null)
                throw Oops.Bah("链接不存在");
            var sugarClient = GenerateSqlSugarClient(dbConnection);
            var allTables = sugarClient.DbMaintenance.GetTableInfoList(false);
            return (allTables.Select(t => t.Name).ToList(), sugarClient);
        }
    }
}
